﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows.Resources;
using System.Device.Location;
using System.Threading;
using SL8.SL.Helpers;
using System.IO.IsolatedStorage;
using System.Diagnostics;
using SL8.SL;

namespace XingZhe.Helpers
{
        public static class Wars2WgsHelper
        {
                private static byte[] TableX_BYTES = null;
                private static byte[] TableY_BYTES = null;
                private static bool InitTable = false;
                //  private static bool IsLoadingText = false;
                private static object IsLoadTextObj = new object();
                private static SynchronousQueue synchronousQueue = new SynchronousQueue();

                // public static event EventHandler LoadDataComplete;

                static Wars2WgsHelper()
                {
                }

                /// <summary>
                /// 火星到GPS
                /// </summary>
                /// <param name="marsLongitude"></param>
                /// <param name="marsLatitude"></param>
                /// <param name="wgsLongitude"></param>
                /// <param name="wgsLatitude"></param>
                private static bool ParseWars2Wgs(double marsLongitude, double marsLatitude, ref double wgsLongitude, ref double wgsLatitude)
                {
                        int i, j, k;
                        double x1, y1, x2, y2, x3, y3, x4, y4, xtry, ytry, dx, dy;
                        double t, u;

                        //if (!InitTable)
                        //{
                        //        Wars2WgsHelper.InitBaseData();


                        //        return false;
                        //}

                        xtry = marsLongitude;
                        ytry = marsLatitude;

                        for (k = 0; k < 10; ++k)
                        {
                                // 只对中国国境内数据转换
                                if (xtry < 72 || xtry > 137.9 || ytry < 10 || ytry > 54.9)
                                {
                                        return false;
                                }

                                i = (int)((xtry - 72.0) * 10.0);
                                j = (int)((ytry - 10.0) * 10.0);

                                x1 = Wars2WgsHelper.GetXValueByIndex(i, j);
                                y1 = Wars2WgsHelper.GetYValueByIndex(i, j);

                                x2 = Wars2WgsHelper.GetXValueByIndex(i + 1, j);
                                y2 = Wars2WgsHelper.GetYValueByIndex(i + 1, j);

                                x3 = Wars2WgsHelper.GetXValueByIndex(i + 1, j + 1);
                                y3 = Wars2WgsHelper.GetYValueByIndex(i + 1, j + 1);

                                x4 = Wars2WgsHelper.GetXValueByIndex(i, j + 1);
                                y4 = Wars2WgsHelper.GetYValueByIndex(i, j + 1);

                                t = (xtry - 72.0 - 0.1 * i) * 10.0;
                                u = (ytry - 10.0 - 0.1 * j) * 10.0;

                                dx = (1.0 - t) * (1.0 - u) * x1 + t * (1.0 - u) * x2 + t * u * x3 + (1.0 - t) * u * x4 - xtry;
                                dy = (1.0 - t) * (1.0 - u) * y1 + t * (1.0 - u) * y2 + t * u * y3 + (1.0 - t) * u * y4 - ytry;

                                xtry = (xtry + marsLongitude - dx) / 2.0;
                                ytry = (ytry + marsLatitude - dy) / 2.0;
                        }

                        wgsLongitude = xtry;
                        wgsLatitude = ytry;

                        return true;
                }

                /// <summary>
                /// GPS到火星
                /// </summary>
                /// <param name="srcGeoCoordinate"></param>
                /// <returns></returns>
                /// 
                public static GeoCoordinate ParseWgs2Wars(GeoCoordinate srcGeoCoordinate)
                {
                        if (Wars2WgsHelper.InitTable == false)
                        {
                                throw new Exception("数据未初始化");
                        }

                        double longitude = 0;
                        double latitude = 0;

                        Stopwatch watch = new Stopwatch();
                        watch.Start();

                        if (Wars2WgsHelper.ParseWars2Wgs(srcGeoCoordinate.Longitude,
                              srcGeoCoordinate.Latitude,
                              ref longitude,
                              ref latitude))
                        {
                                GeoCoordinate geoCoordinate = new GeoCoordinate()
                                {
                                        Altitude = srcGeoCoordinate.Altitude,
                                        Course = srcGeoCoordinate.Course,
                                        HorizontalAccuracy = srcGeoCoordinate.HorizontalAccuracy,
                                        //Latitude = srcGeoCoordinate.Latitude - ZhuGeMapHelper.SystemConfig.LastOffsetLatitude,
                                        //Longitude = srcGeoCoordinate.Longitude - ZhuGeMapHelper.SystemConfig.LastOffsetLongitude,

                                        Latitude = srcGeoCoordinate.Latitude - (latitude - srcGeoCoordinate.Latitude),
                                        Longitude = srcGeoCoordinate.Longitude - (longitude - srcGeoCoordinate.Longitude),

                                        Speed = srcGeoCoordinate.Speed,
                                        VerticalAccuracy = srcGeoCoordinate.VerticalAccuracy
                                };

                                watch.Stop();
                                Debug.WriteLine("修正耗时：{0}", watch.ElapsedMilliseconds);

                                return geoCoordinate;
                        }
                        else
                        {
                                return srcGeoCoordinate;
                        }
                }
                public static void ParseWgs2Wars(GeoCoordinate srcGeoCoordinate, Action<GeoCoordinate> onComplate)
                {
                        Wars2WgsHelper.InitBaseData(() =>
                        {
                                GeoCoordinate geoCoordinate = Wars2WgsHelper.ParseWgs2Wars(srcGeoCoordinate);

                                if (onComplate != null)
                                {
                                        onComplate(geoCoordinate);
                                }
                        });
                }
                public static void InitBaseData(Action onComplete)
                {
                        // 没有在加载偏移数据
                        if (Wars2WgsHelper.InitTable == false)
                        {
                                lock (Wars2WgsHelper.IsLoadTextObj)
                                {
                                        if (Wars2WgsHelper.InitTable == false)
                                        {
                                                Wars2WgsHelper.InitTable = true;
                                                Wars2WgsHelper.synchronousQueue.EnqueueAction(() =>
                                                {
                                                        ThreadPool.QueueUserWorkItem((obj) =>
                                                        {
                                                                Wars2WgsHelper.LoadText();
                                                                System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
                                                                {
                                                                        Wars2WgsHelper.synchronousQueue.DequeueAction();
                                                                });
                                                        });
                                                });
                                        }
                                }
                        }

                        Wars2WgsHelper.synchronousQueue.EnqueueAction(() =>
                        {
                                if (onComplete != null)
                                {
                                        onComplete();
                                }

                                Wars2WgsHelper.synchronousQueue.DequeueAction();
                        });
                }
                private static void LoadText()
                {
                        System.Diagnostics.Stopwatch stopwatch = new Stopwatch();

                        stopwatch.Start();
                        //StreamResourceInfo stream = Application.GetResourceStream(new Uri("Assets/Data/TableX.dat", UriKind.Relative));

                        //if (stream != null && stream.Stream != null)
                        //{
                        //        using (StreamReader sr = new StreamReader(stream.Stream))
                        //        {
                        //                string s = sr.ReadToEnd();
                        //                Wars2WgsHelper.TableX = s.Split('\n');
                        //        }
                        //}

                        //StreamResourceInfo streamY = Application.GetResourceStream(new Uri("Assets/Data/TableY.dat", UriKind.Relative));

                        //if (streamY != null && streamY.Stream != null)
                        //{
                        //        using (StreamReader sr = new StreamReader(streamY.Stream))
                        //        {
                        //                string s = sr.ReadToEnd();
                        //                Wars2WgsHelper.TableY = s.Split('\n');
                        //        }
                        //}


                        StreamResourceInfo streamX = Application.GetResourceStream(new Uri("Assets/Data/TableX_New.dat", UriKind.Relative));

                        if (streamX != null && streamX.Stream != null)
                        {
                                Wars2WgsHelper.TableX_BYTES = new byte[streamX.Stream.Length];
                                streamX.Stream.Read(Wars2WgsHelper.TableX_BYTES, 0, Wars2WgsHelper.TableX_BYTES.Length);
                                streamX.Stream.Close();
                        }

                        StreamResourceInfo streamY = Application.GetResourceStream(new Uri("Assets/Data/TableY_New.dat", UriKind.Relative));

                        if (streamY != null && streamY.Stream != null)
                        {
                                Wars2WgsHelper.TableY_BYTES = new byte[streamY.Stream.Length];
                                streamY.Stream.Read(Wars2WgsHelper.TableY_BYTES, 0, Wars2WgsHelper.TableY_BYTES.Length);
                                streamY.Stream.Close();
                        }

                        stopwatch.Stop();

                        Debug.WriteLine("加载偏移数据：{0}毫秒", stopwatch.ElapsedMilliseconds);
                }

                private static double GetXValueByIndex(int I, int J)
                {
                        float value = BitConverter.ToSingle(Wars2WgsHelper.TableX_BYTES, (I + 660 * J) * 4);
                        return double.Parse(value.ToString());
                }

                private static double GetYValueByIndex(int I, int J)
                {
                        float value = BitConverter.ToSingle(Wars2WgsHelper.TableY_BYTES, (I + 660 * J) * 4);
                        return double.Parse(value.ToString());
                }
        }
}
